# coding=UTF-8
"""
Copyright Ian Ross Williams, 2012

    This file is part of ArcSecond.

    ArcSecond is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    ArcSecond is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ArcSecond.  If not, see <http://www.gnu.org/licenses/>.
"""

import pygtk
pygtk.require('2.0')
import gtk.gdk
import StringIO
import Image,ImageDraw
import os

class notebook_view_stack():
    statusbarLeft=None
    statusbarLeftID=None
    image = None           #The contents of the drawing area
    frameList = []
    width = 640             #Resolution of the camera
    height = 480        
    zoom = 1
    ROI = None
    registered=False
    
    def __init__(self,statusbar,id):
        self.statusbarLeft=statusbar
        self.statusbarLeftID=id

    def set_frames(self, frameList):
        if len(frameList)>0:
            self.frameList = frameList
            self.frameAdjuster.set_lower(1)
            self.frameAdjuster.set_upper(len(frameList))
            if self.frameAdjuster.get_value()==0:
                self.frameAdjuster.set_value(1)
            self.select_frame_callback(self.frameAdjuster)
                
    def select_frame(self, frameNo):
        if len(self.frameList)>0:
            self.frameAdjuster.set_value(frameNo)
    
    def select_next(self):
        if len(self.frameList)>0:
            frameNo = self.frameAdjuster.get_value() + 1
            if frameNo>self.frameAdjuster.get_upper(): frameNo=self.frameAdjuster.get_lower()
            self.frameAdjuster.set_value(frameNo)
        
    def select_previous(self):
        if len(self.frameList)>0:
            frameNo = self.frameAdjuster.get_value() - 1
            if frameNo<self.frameAdjuster.get_lower(): frameNo=self.frameAdjuster.get_upper()
            self.frameAdjuster.set_value(frameNo)        

    def select_frame_callback(self, frameAdjuster):
        frameNo = int(frameAdjuster.get_value())
        imageFile = self.frameList[frameNo-1]
        
        if self.registered:
            path = os.path.dirname(imageFile) + "/registered"
            registeredFile=path + "/" + os.path.basename(imageFile)
            if os.path.exists(registeredFile):
                imageFile = registeredFile
            
        im = Image.open(imageFile)
        msg = "(%d) %s" % (frameNo, imageFile)
        self.statusbarLeft.pop(self.statusbarLeftID)
        self.statusbarLeft.push(self.statusbarLeftID, msg)        
            
        self.image = im  
        self.width,self.height = im.size
        self.drawingArea.set_size_request(self.width, self.height)
        self.drawingArea.queue_draw() 
        
    def registered_toggled(self, cb):
        self.registered = not self.registered
        self.select_frame_callback(self.frameAdjuster) 
        
    # Create a new backing pixmap of the appropriate size
    def configure_event(self, widget, event):
        x, y, width, height = widget.get_allocation()
        pixmap = gtk.gdk.Pixmap(widget.window, width, height)
        pixmap.draw_rectangle(widget.get_style().white_gc,
                              True, 0, 0, width, height)
    
    # Displays the currently selected frame 
    def expose_event(self, widget, event):
        if self.image:
            im = self.image
            if self.ROI and not self.registered:
                im = self.image.copy()
                draw=ImageDraw.Draw(im)
                draw.rectangle(self.ROI,outline=128)
            pixbuf = self.image2pixbuf(im)
            widget.window.draw_pixbuf(None,pixbuf, 0, 0, 0, 0, self.width, self.height) 

    def button_press_event(self, widget, event):
        if event.button == 1 and self.image != None and not self.registered:
            self.ROI = [event.x,event.y,event.x,event.y]

    def button_release_event(self, widget, event):
        if event.button == 1 and self.image != None:
            self.ROI = [min(self.ROI[0],event.x),min(self.ROI[1],event.y),
                        max(self.ROI[0],event.x),max(self.ROI[1],event.y)]
            sx = self.ROI[2] - self.ROI[0]
            sy = self.ROI[3] - self.ROI[1]
            self.statusbarLeft.pop (self.statusbarLeftID)
            self.statusbarLeft.push(self.statusbarLeftID,
               "Region of interest: [%d,%d] to [%d,%d], size=%dx%d" % (self.ROI[0],self.ROI[1],self.ROI[2],self.ROI[3],sx,sy) ) 
            self.drawingArea.queue_draw()

    def motion_notify_event(self,widget,event): 
        if event.is_hint:
            x, y, state = event.window.get_pointer()
        else:
            x = event.x
            y = event.y
            state = event.state
        
        if state & gtk.gdk.BUTTON1_MASK and self.image != None and self.ROI!=None:
            self.ROI = [self.ROI[0],self.ROI[1],x,y]
            displayROI = [min(self.ROI[0],x),min(self.ROI[1],y),
                        max(self.ROI[0],x),max(self.ROI[1],y)]
            sx = displayROI[2] - displayROI[0]
            sy = displayROI[3] - displayROI[1]
            self.statusbarLeft.pop (self.statusbarLeftID)
            self.statusbarLeft.push(self.statusbarLeftID,
               "Region of interest: [%d,%d] to [%d,%d], size=%dx%d" % (displayROI[0],displayROI[1],displayROI[2],displayROI[3],sx,sy) ) 
            self.drawingArea.queue_draw()
            
        return True

    def get_ROI(self):
        return self.ROI
    
    def clear_ROI(self):
        self.ROI=None
        self.statusbarLeft.pop(self.statusbarLeftID)
        self.statusbarLeft.push(self.statusbarLeftID, "Cleared the Region of Interest")
        self.drawingArea.queue_draw()

    def get_page(self):
        hbox = gtk.HBox()
        vboxLeft = gtk.VBox()
        hbox.pack_start(vboxLeft,False,False)
        
        self.checkbuttonRegistered = gtk.CheckButton("Registered")
        self.checkbuttonRegistered.connect("toggled", self.registered_toggled)
        vboxLeft.pack_start(self.checkbuttonRegistered,False,False)
        
        #Construct the capture view area
        scrolledWindow = gtk.ScrolledWindow()
        scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) 
        self.drawingArea = gtk.DrawingArea()
        self.drawingArea.set_size_request(self.width, self.height)
        scrolledWindow.add_with_viewport(self.drawingArea)         
        hbox.pack_end(scrolledWindow, expand=True, fill=True, padding=0)
        
        # Signals used to handle backing pixmap
        self.drawingArea.connect("configure_event", self.configure_event)
        self.drawingArea.connect("expose_event", self.expose_event)
    
        # Event signals
        self.drawingArea.connect("button_press_event", self.button_press_event)
        self.drawingArea.connect("button_release_event", self.button_release_event)
        self.drawingArea.connect("motion_notify_event", self.motion_notify_event)
        
        self.drawingArea.set_events(gtk.gdk.EXPOSURE_MASK
                                | gtk.gdk.LEAVE_NOTIFY_MASK
                                | gtk.gdk.BUTTON_PRESS_MASK
                                | gtk.gdk.BUTTON_RELEASE_MASK
                                | gtk.gdk.POINTER_MOTION_MASK
                                | gtk.gdk.POINTER_MOTION_HINT_MASK)

        #Construct a horizontal slider to select the frames
        frame = gtk.Frame("Frame:")
        self.frameAdjuster = gtk.Adjustment(value=0, lower=0, upper=0, step_incr=1, page_incr=1, page_size=0)
        self.spinbutton = gtk.SpinButton(self.frameAdjuster)
        self.spinbutton.set_digits(0)
        frame.add(self.spinbutton)
        self.frameAdjuster.connect("value-changed", self.select_frame_callback)
        vboxLeft.pack_start(frame,False,False,0)
        
        hbox.show_all()
        return hbox

    def image2pixbuf(self,im):    
        if im:
            file1 = StringIO.StringIO()  
            im.save(file1, "ppm")  
            contents = file1.getvalue()  
            file1.close()  
            loader = gtk.gdk.PixbufLoader("pnm")  
            loader.write(contents, len(contents))  
            pixbuf = loader.get_pixbuf()  
            loader.close()
            return pixbuf
